package com.xcity.db.entity;

import java.text.MessageFormat;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.annotation.JSONField;
import com.xcity.game.build.BuildLevelUpTemplate;
import com.xcity.game.build.BuildManager;
import com.xcity.game.build.BuildRef;
import com.xcity.game.build.BuildTemplate;
import com.xcity.game.build.BuildUtils;
import com.xcity.game.common.Cause;
import com.xcity.game.common.MessageConst;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.conquests.Conquest;
import com.xcity.game.event.GameEvents;
import com.xcity.game.item.ItemInfo;
import com.xcity.game.item.ItemTemplate;
import com.xcity.game.item.listener.BagListener;
import com.xcity.game.player.PlayerUtils;
import com.xcity.game.player.cache.PlayerCacheService;
import com.xcity.game.skill.SkillTypes;
import com.xcity.pomelo.push.SyncPush;
import com.xcity.pomelo.push.msg.TipPush;
import com.xcity.pomelo.push.sync.CustomSync;
import com.xcity.pomelo.response.BuildListStatusResponse.BuildStatusRes;

import naga.x.App;
import naga.x.game.template.TemplateService;
import naga.x.game.time.TimeUpdater;

@Deprecated
public class Build implements BagListener {

	@JSONField(name = "0")
	private int id;
	@JSONField(name = "1")
	private int level;
	@JSONField(name = "2")
	private long createTime;
	@JSONField(name = "3")
	private long buildingEndTime; // 建造/升级结束时间
	@JSONField(name = "4")
	private long lastTakeMoneyTime;
	@JSONField(name = "5")
	private State state = State.FREE;
	@JSONField(name = "6")
	private int tempMoney; // 未入账的累计收益
	@JSONField(name = "7")
	private long lastAddReserveTime;
	@JSONField(name = "8")
	private int reserve; // 储备力
	@JSONField(name = "9")
	private long[] employees; // 该建筑中的员工
	@JSONField(name = "10")
	private long restEndTime; // 休店期结束时间
	@JSONField(name = "11")
	private long attackerId; // 攻击者
	@JSONField(name = "12")
	private int tryAddLevel; // 尝试增加等级(每次升级时累加，升级完成时重置为0)
	@JSONField(name = "13")
	private long capturedOperateTimeout; // 攻占后操作超时时间
//	@JSONField(name = "14")
//	private CapturedState capturedState; // 被攻占后，攻占方操作状态
//	@JSONField(name = "15")
//	private long[] employeesOfAttacker; // 被攻占后，攻占方驻守在该建筑的员工
	
	@JSONField(serialize = false, deserialize = false)
	private BuildTemplate template;
	@JSONField(serialize = false, deserialize = false)
	private BuildManager manager;
	
	public static final int BREAK_LEVEL = 10; // 突破等级
	public static final int MAX_SLOT = 4; // 最大员工槽位
	public static final int ADD_RESERVE_CD = (int) TimeUnit.MINUTES.toMillis(3); // 每3分钟点击收钱可增加1点储备力
	public static final float ADD_RESERVE_PERCENT = 0.3f;
	public static final int REDUCE_RESERVE_CD = (int) TimeUnit.HOURS.toMillis(1); // 连续1小时没点击收钱则降低5点储备力
	public static final int REDUCE_RESERVE_VALUE = 5;
	public static final int MAX_RESERVE = 100;
	public static final int BUILD_QUEUE_BASIC_SIZE = 1; // 建筑队列初始值
	public static final int CAPTURE_OPERATE_TIMEOUT = 60000; // 攻占后有效操作的超时时间
	
	protected static final Logger LOG = LoggerFactory.getLogger(Build.class);
	
	public static enum State {
		FREE, // 空闲状态
		BUILDING, // 建造/升级状态
		REST, // 休店期
		CAPTURED, // 被占领
		;
		public byte codeOfOldVersion() {
			switch (this) { // 兼容老版本
				case FREE:
					return 1;
				case BUILDING:
					return 0;
//				case REST:
//					return 2;
				default:
					return (byte) ordinal();
			}
		}
	}
	
//	public static enum CapturedState {
//		WAITING, // 等待攻占者操作
//		GIVEN_UP_CAPTURE, // 放弃占领
//		CAPTURED, // 已派遣员工驻守占领
//	}
	
	public Build() {
	}
	
	public Build(int id, BuildManager manager) {
		this.id = id;
		this.level = 0;
		long now = TimeUpdater.getInstance().now();
		this.createTime = now;
//		this.buildingEndTime = now;
		this.lastTakeMoneyTime = now;
//		this.state = State.BUILDING;
		this.manager = manager;
		this.reserve = MAX_RESERVE;
		tryLevelUp();
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public long getCreateTime() {
		return createTime;
	}

	public void setCreateTime(long createTime) {
		this.createTime = createTime;
	}

	public long getBuildingEndTime() {
		return buildingEndTime;
	}

	public void setBuildingEndTime(long buildingEndTime) {
		this.buildingEndTime = buildingEndTime;
	}

	public long getLastTakeMoneyTime() {
		return lastTakeMoneyTime;
	}

	public void setLastTakeMoneyTime(long lastTakeMoneyTime) {
		this.lastTakeMoneyTime = lastTakeMoneyTime;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}
	
	public int getTempMoney() {
		return tempMoney;
	}

	public void setTempMoney(int tempMoney) {
		this.tempMoney = tempMoney;
	}
	
	public void addTempMoney(int val) {
		if (val > 0) {
			tempMoney += val;
		}
	}

	public long getLastAddReserveTime() {
		return lastAddReserveTime;
	}

	public void setLastAddReserveTime(long lastAddReserveTime) {
		this.lastAddReserveTime = lastAddReserveTime;
	}
	
	public int getTryAddLevel() {
		return tryAddLevel;
	}

	public void setTryAddLevel(int tryAddLevel) {
		this.tryAddLevel = tryAddLevel;
	}

	public long[] getEmployees() {
		return employees;
	}

	public void setEmployees(long[] employees) {
		this.employees = employees;
	}
	
//	public long[] getEmployeesOfAttacker() {
//		return employeesOfAttacker;
//	}
//
//	public void setEmployeesOfAttacker(long[] employeesOfAttacker) {
//		this.employeesOfAttacker = employeesOfAttacker;
//	}
	
	public long getRestEndTime() {
		return restEndTime;
	}

	public void setRestEndTime(long restEndTime) {
		this.restEndTime = restEndTime;
	}

	public long getAttackerId() {
		return attackerId;
	}

	public void setAttackerId(long attackerId) {
		this.attackerId = attackerId;
	}
	
	public long getCapturedOperateTimeout() {
		return capturedOperateTimeout;
	}

	public void setCapturedOperateTimeout(long capturedOperateTimeout) {
		this.capturedOperateTimeout = capturedOperateTimeout;
	}

//	public CapturedState getCapturedState() {
//		return capturedState;
//	}
//
//	public void setCapturedState(CapturedState capturedState) {
//		this.capturedState = capturedState;
//	}

	public BuildTemplate getTemplate() {
		return template != null ? template : (template = App.getApp().getServiceManager().get(TemplateService.class).get(BuildTemplate.class, id));
	}
	
	@JSONField(serialize = false)
	public BuildLevelUpTemplate getBuildLevelUpTemplate() {
		return getTemplate().getLevelUpTemplate(level);
	}
	
	@JSONField(serialize = false)
	public float getFactor() {
		Player player = manager.getOwner();
		float factor = player.getPool().getFloatValue(PlayerPool.PROPERTY_BUILD_INCOME_FACTOR_PREFIX + getTemplate().getGroup());
		if (factor <= 0f) {
			factor = 1f;
		}
//		WorldEvent event = App.getApp().getServiceManager().get(WorldEventService.class).getCurrentEvent();
//		if (event != null && !event.isGood()) {
//		}
		float baseFactor = factor;
		if (factor < 1f) { // 世界事件debuff时需计算员工aq系数
			factor += BuildUtils.getAQFactorOfEmployees(this) / 100f;
		}
		
		if (factor < 1f) { // 世界事件debuff
			Float f = player.getEmployees().calc(SkillTypes.REDUCE_BAD_WORLD_EVENT_LOSSES, getEmployees());
			if (f != null && f > 0f) {
				factor += (1f - baseFactor) * f / 100f;
			}
		}
		if (factor > 1f) { // 世界事件buff
			Float f = player.getEmployees().calc(SkillTypes.ADD_GOOLD_WORLD_EVENT_INCOME, getEmployees());
			if (f != null && f > 0f) {
				factor += f / 100f;
			}
		}
		
		return factor > 0f ? factor : 1f;
	}
	
	public int settle() {
		return settle(false);
	}
	
	public int settle(boolean reset) {
		return settle(TimeUpdater.getInstance().now(), reset);
	}
	
	/**
	 * 结算收益
	 * @param endTime
	 * @param reset
	 * @return
	 */
	public int settle(long endTime, boolean reset) {
		if (state != State.FREE && state != State.CAPTURED) {
			return 0;
		}
		long elapse = endTime - lastTakeMoneyTime;
		if (elapse <= 0 && tempMoney == 0) {
			return 0;
		}
//		BuildLevelUpTemplate temp = getTemplate().getLevelUpTemplate(level);
		int money = 0;
		int maxIncome = getMaxIncome();
		if (elapse > 0) {
			money = (int) (elapse * getIncomePerMinute()/*temp.getIncome()*/ * getFactor() / 60000);
		}
		money += tempMoney;
		if (reset) {
//			resetIncome();
			tempMoney = 0;
			if (endTime > buildingEndTime) {
				lastTakeMoneyTime = endTime;
			}
		}
		return money > maxIncome ? maxIncome : money;
	}
	
	public void resetIncome() {
		tempMoney = 0;
		lastTakeMoneyTime = TimeUpdater.getInstance().now();
	}
	
	@JSONField(serialize = false)
	public int getIncomePerMinute() {
		BuildLevelUpTemplate temp = getBuildLevelUpTemplate();
		Float f = manager.getOwner().getEmployees().calc(SkillTypes.ADD_BUILD_INCOME, getEmployees());
		Float f2 = manager.getOwner().getEmployees().calc(SkillTypes.ADD_BUILD_INCOME_ONLY_ONE_EMPLOYEE, getEmployees());
		if (f2 != null && f2 > 0f) {
			f += f2;
		}
		return f != null && f > 0f ? (int) (temp.getIncome() * (100 + f) / 100f) : temp.getIncome();
	}
	
	@JSONField(serialize = false)
	public int getMaxIncome() {
		BuildLevelUpTemplate temp = getBuildLevelUpTemplate();
		Float f = manager.getOwner().getEmployees().calc(SkillTypes.ADD_BUILD_INCOME, getEmployees());
		Float f2 = manager.getOwner().getEmployees().calc(SkillTypes.ADD_BUILD_INCOME_ONLY_ONE_EMPLOYEE, getEmployees());
		if (f2 != null && f2 > 0f) {
			f += f2;
		}
		return f != null && f > 0f ? (int) (temp.getMaxIncome() * (100 + f) / 100f) : temp.getMaxIncome();
	}
	
	@JSONField(serialize = false)
	public int getLeftCD() {
		if (state == State.BUILDING) {
			long cd = buildingEndTime - TimeUpdater.getInstance().now();
			return (int) (cd > 0 ? cd : 0);
		}
		return 0;
	}
	
	public void tryLevelUp() {
		if (level + tryAddLevel >= BuildUtils.getMaxLevel(this)) {
			return;
		}
		if (tryAddLevel++ == 0) {
			buildingEndTime = TimeUpdater.getInstance().now();
		}
		BuildLevelUpTemplate temp = getTemplate().getLevelUpTemplate(level + tryAddLevel);
		buildingEndTime += temp.getCd() * 1000;
		state = State.BUILDING;
	}
	
	public void levelUp(String cause) {
		int exp = 0; // 建造经验
		for (int i = 1; i <= tryAddLevel; i++) {
			BuildLevelUpTemplate temp = getTemplate().getLevelUpTemplate(level + i);
			exp += temp.getExp();
		}
		Player player = manager.getOwner();
		if (exp > 0) {
			player.addExp(exp, Cause.BUILD_LEVEL_UP);
			if (TimeUpdater.getInstance().now() - player.getLastLoginTime().getTime() > 1000) { // 避免上线时提示
				player.send(new TipPush(MessageFormat.format(MessageConst.BUILD_FINISH_ADD_EXP, exp)));
			}
		}
		
		level += tryAddLevel;
		tryAddLevel = 0;
		int maxLvl = BuildUtils.getMaxLevel(this);
		if (level > maxLvl) {
			level = maxLvl;
		}
		state = State.FREE;
		lastTakeMoneyTime = TimeUpdater.getInstance().now();
		if (level > BREAK_LEVEL && lastAddReserveTime == 0) {
			lastAddReserveTime = TimeUpdater.getInstance().now();
			reserve = MAX_RESERVE;
		}
		ref = null;
		refer();
		
		player.send(new CustomSync(SyncPush.SYNC_BUILD, new BuildStatusRes(player, this)));
		App.getApp().getEventManager().addEvent(GameEvents.EVENT_BUILDING_LEVEL_UP_OK, player, this);
		LOG.info("[BUILD LVLUP]ID[{}]BUILD[{}]LVL[{}]CAUSE[{}]", player.getId(), id, level, cause);
	}
	
	@JSONField(serialize = false)
	public BuildLevelUpTemplate getNextLevelTemplate() {
		return getTemplate().getLevelUpTemplate(level + 1);
	}
	
	/**
	 * 获取当前员工槽位
	 * @return
	 */
	@JSONField(serialize = false)
	public int getSlot() {
		// level-slot: 11-1 15-2 20-3 30-4
		if (level >= 30)
			return MAX_SLOT;
		if (level >= 20)
			return MAX_SLOT - 1;
		if (level >= 15)
			return MAX_SLOT - 2;
		if (level > BREAK_LEVEL)
			return MAX_SLOT - 3;
		return 0;
	}
	
	/**
	 * <pre>
	 * 抵抗力(防御)
	 * （基础抵抗力+储备力*系数2.25）*人物等级系数+员工抵抗力（带宠物及奢侈品加成）+(固资加成 * 系数)
	 * 人物等级系数	当人物到达某一级别后，在达到下一级别系数前，可获得的加成比例
	 * 人物等级系数1	1.03
	 * 人物等级系数2	1.06
	 * 人物等级系数3	1.09
	 * 人物等级系数4	1.12
	 * 人物等级系数5	1.15
	 * </pre>
	 * @return
	 */
	@JSONField(serialize = false)
	public float getDefense() {
		if (level <= BREAK_LEVEL) {
			return 0;
		}
		Player player = manager.getOwner();
		int basicDefense = getBuildLevelUpTemplate().getBasicDefense();
		int reserve = calcReserve();
		float employeesDefense = 0f;
		long[] employeeIds = getEmployees();
		float employeeSkillAddedRatio = 0f; // 员工技能加成
		if (employeeIds != null) {
			for (long eid : employeeIds) {
				Employee e;
				if (eid != 0 && (e = player.getEmployees().get(eid)) != null) {
					employeesDefense += e.getDefense();
//					EmployeeSkill skill = e.getSkillByGroup(SkillGroups2.RAISE_BUILD_DEFENSE.ordinal());
//					if (skill != null) {
//						employeeSkillAddedRatio += skill.getValue(0) / GameStaticConfig.percentBase;
//					}
				}
			}
		}
		long fixAssets = player.getFixedAssets();
		float playerFactor = PlayerUtils.getPlayerFactor(player);
		float defense = (basicDefense + reserve * 2.25f) * playerFactor + employeesDefense + fixAssets * 0.000235f;
		if (employeeSkillAddedRatio > 0) {
			defense += defense * employeeSkillAddedRatio;
		}
		return defense;
	}
	
	/**
	 * 储备力
	 * @return
	 */
//	@JSONField(serialize = false) // 需要持久化
	public int getReserve() {
		return reserve;
	}
	
	public int calcReserve() {
		Number n = manager.getOwner().getEmployees().calc(SkillTypes.ADD_BUILD_RESERVE, getEmployees());
		int val = reserve + (n != null ? n.intValue() : 0);
		return val;
	}
	
	public int calcMaxReserve() {
		Number n = manager.getOwner().getEmployees().calc(SkillTypes.ADD_BUILD_RESERVE, getEmployees());
		return MAX_RESERVE + (n != null ? n.intValue() : 0);
	}
	
	public void setReserve(int reserve) {
		this.reserve = reserve;
	}
	
	public void addReserve(int val, String cause) {
		int oldVal = this.reserve;
		this.reserve += val;
		int maxVal = calcMaxReserve();
		if (this.reserve > maxVal) {
			this.reserve = maxVal;
		}
		LOG.info("[BUILD ADD RESERVE]ID[{}]BUILD[{}]OLD[{}]NEW[{}]CAUSE[{}]", manager.getOwner().getId(), id, oldVal, this.reserve, cause);
	}
	
	public void decReserve(int val, String cause) {
		int oldVal = this.reserve;
		this.reserve -= val;
		if (this.reserve < 0) {
			this.reserve = 0;
		}
		LOG.info("[BUILD DEC RESERVE]ID[{}]BUILD[{}]OLD[{}]NEW[{}]CAUSE[{}]", manager.getOwner().getId(), id, oldVal, this.reserve, cause);
	}
	
	/**
	 * 自救力(减少休店期cd)
	 * @return
	 */
	@JSONField(serialize = false)
	public int getCure() {
		Number n = manager.getOwner().getEmployees().calc(SkillTypes.ADD_BUILD_CURE, getEmployees());
		return n != null ? n.intValue() : 0;
	}
	
	public void addEmployee(Employee employee, int pos) {
		if (pos < 0 || pos >= getSlot()) {
			return;
		}
		if (employees == null) {
			employees = new long[MAX_SLOT];
		}
		long oldEmployeeId = employees[pos];
		if (oldEmployeeId != 0) {
			Employee oldEmployee = manager.getOwner().getEmployees().get(oldEmployeeId);
			if (oldEmployee != null) {
				oldEmployee.setState(com.xcity.db.entity.Employee.State.FREE, true);
			}
		}
		employee.setState(com.xcity.db.entity.Employee.State.DEFENSE, true);
		employees[pos] = employee.getId();
	}
	
	public int removeEmployee(Employee employee) {
		if (employees == null) {
			return -1;
		}
		for (int i = 0; i < employees.length; i++) {
			if (employees[i] == employee.getId()) {
				employees[i] = 0;
				employee.setState(com.xcity.db.entity.Employee.State.FREE, true);
				return i;
			}
		}
		return -1;
	}

	public void update() {
		if (level > BREAK_LEVEL) {
			long elapse = TimeUpdater.getInstance().now() - lastAddReserveTime;
			if (elapse >= REDUCE_RESERVE_CD) {
				lastAddReserveTime = TimeUpdater.getInstance().now() - elapse % REDUCE_RESERVE_CD;
				int n = (int) (elapse / REDUCE_RESERVE_CD);
				decReserve(n * REDUCE_RESERVE_VALUE, Cause.AUTO);
			}
		}
		if (state == State.REST
				&& getLeftRestCD() <= 0) {
			restOver();
		}
		if (state == State.FREE && attackerId != 0L && wasCapturedOperateTimeout()) {
			attackerId = 0L;
		}
//		if (capturedState == CapturedState.WAITING && wasCapturedOperateTimeout()) {
//			// 攻占方长时间未操作(超时)则重置建筑状态
//			capturedState = CapturedState.GIVEN_UP_CAPTURE;
//		}
//		if (capturedState == CapturedState.GIVEN_UP_CAPTURE && state == State.CAPTURED) {
//			state = State.FREE;
//			attackerId = 0L;
//		}
	}

	public void setManager(BuildManager manager) {
		this.manager = manager;
	}
	
	public BuildManager getManager() {
		return manager;
	}

	/**
	 * 进入休店期
	 * @param attacker
	 * @param reduceCdPercent 减少cd百分比
	 */
	public void rest(Player attacker, float reduceCdPercent) {
		unCaptureForce();
		int cd = getBuildLevelUpTemplate().getRestCD() * 60000;
		if (reduceCdPercent > 0) {
			cd -= cd * reduceCdPercent / 100;
		}
		if (cd < 0) {
			cd = 0;
		}
		state = State.REST;
		restEndTime = TimeUpdater.getInstance().now() + cd;
		capturedOperateTimeout = TimeUpdater.getInstance().now() + CAPTURE_OPERATE_TIMEOUT;
//		capturedState = CapturedState.WAITING;
		attackerId = attacker.getId();// != getManager().getOwner().getId() ? attacker.getId() : 0L;
//		employeesOfAttacker = null;
	}
	
	private void unCaptureForce() {
		if (state != State.CAPTURED) {
			return;
		}
		Player player = attacker();
		if (player != null) {
			unCapture(player, Cause.FORCE);
//			Conquest c = player.getConquests().remove(this);
//			long[] eids = employees();
//			boolean dirty = false;
//			for (int i = 0, len = eids != null ? eids.length : 0; i < len; i++) {
//				long eid = eids[i];
//				Employee e = eid != 0L ? player.getEmployees().get(eid) : null;
//				if (e != null) {
//					e.setState(Employee.State.FREE);
//					dirty = true;
//				}
//			}
//			if (player instanceof Actor) {
//				((Actor) player).setDirty(true);
//			}
		}
	}
	
	public void restOver() {
		Player player = manager.getOwner();
		state = State.FREE;
//		attackerId = 0L;
		resetIncome();
		if (employees != null) {
			for (long eid : employees) {
				Employee employee = player.getEmployees().get(eid);
				if (eid != 0 && (employee = player.getEmployees().get(eid)) != null) {
//					float v = employee.getSkillValue(SkillTypes.GET_INCOME_AFTER_REST, 0);
//					if (v > 0f) {
//						int income = (int) (getMaxIncome() * v / 100f);
//						addTempMoney(income);
//						LOG.info("[EMPLOYEE SKILL 22 TRIGGER]ID[{}]BUILD[{}]INCOME[{}]", manager.getOwner().getId(), id, income);
//						break;
//					}
				}
			}
		}
		
		if (player.isOnline()) {
			player.send(new CustomSync(SyncPush.SYNC_BUILD, new BuildStatusRes(player, this)));
		}
	}
	
	/**
	 * 休店期剩余cd
	 * @return
	 */
	@JSONField(serialize = false)
	public int getLeftRestCD() {
		if (state == State.REST || state == State.CAPTURED) {
			long leftCd = restEndTime - TimeUpdater.getInstance().now();
			return (int) (leftCd > 0 ? leftCd : 0);
		}
		return 0;
	}
	
	@JSONField(serialize = false)
	public String getName() {
		return getTemplate().getName(level);
	}
	
	/**
	 * 攻占方派遣员工占领该建筑
	 * @param attacker
	 * @param eids
	 */
	public synchronized long[] capture(Player attacker, List<Employee> employees, String cause) {
//		if (capturedState != CapturedState.WAITING) {
//			return null;
//		}
		if (attacker.getId() != attackerId || state == State.CAPTURED || wasCapturedOperateTimeout()) {
			return null;
		}
//		long[] eids = new long[employees.size()];
//		for (int i = 0; i < employees.size(); i++) {
//			Employee e = employees.get(i);
////			e.getPool().put(EmployeePool.CAPTURED_PLAYER_ID, getManager().getOwner().getId());
////			e.getPool().put(EmployeePool.CAPTURED_PLAYER_BUILD_ID, getId());
//			e.changeState(com.xcity.db.entity.Employee.State.DEFENSE_OTHER_BUILD);
//			eids[i] = e.getId();
//		}
		Conquest c = attacker.getConquests().add(this, employees);
		state = State.CAPTURED;
//		employeesOfAttacker = eids;
//		capturedState = CapturedState.CAPTURED;
//		if (attacker instanceof Actor) {
//			((Actor) attacker).setDirty(true);
//		}
		Player owner = getManager().getOwner();
//		if (owner instanceof Actor) {
//			((Actor) owner).setDirty(true);
//		}
		if (owner.isOnline()) {
			owner.send(new CustomSync(SyncPush.SYNC_BUILD, new BuildStatusRes(owner, this)));
		}
		LOG.info("[BUILD CAPTURE]ID[{}]DEST[{}]BUILD[{}]EMPLOYEES[{}]CAUSE[{}]", attacker.getId(), getManager().getOwner().getId(), getId(), c != null ? c.getEmployees() : null, cause);
		return c != null ? c.getEmployees() : null;
	}
	
	/**
	 * 放弃占领
	 */
	public synchronized long[] unCapture(Player attacker, String cause) {
//		if (capturedState == CapturedState.GIVEN_UP_CAPTURE) {
//			return null;
//		}
		if (attacker.getId() != attackerId/* || employeesOfAttacker == null*/) {
			return null;
		}
		Conquest c = attacker.getConquests().remove(this);
//		for (int i = 0, len = employeesOfAttacker != null ? employeesOfAttacker.length : 0; i < len; i++) {
//			Employee e = attacker.getEmployees().get(employeesOfAttacker[i]);
//			if (e != null) {
//				e.changeState(com.xcity.db.entity.Employee.State.FREE);
//				e.getPool().remove(EmployeePool.CAPTURED_PLAYER_ID);
//				e.getPool().remove(EmployeePool.CAPTURED_PLAYER_BUILD_ID);
//			}
//		}
		state = State.FREE;
		attackerId = 0L;
//		long[] eids = employeesOfAttacker;
//		employeesOfAttacker = null;
//		capturedState = CapturedState.GIVEN_UP_CAPTURE;
//		if (attacker instanceof Actor) {
//			((Actor) attacker).setDirty(true);
//		}
		Player owner = getManager().getOwner();
//		if (owner instanceof Actor) {
//			((Actor) owner).setDirty(true);
//		}
		if (owner.isOnline()) {
			owner.send(new CustomSync(SyncPush.SYNC_BUILD, new BuildStatusRes(owner, this)));
		}
		LOG.info("[BUILD UNCAPTURE]ID[{}]DEST[{}]BUILD[{}]CAUSE[{}]", attacker.getId(), getManager().getOwner().getId(), getId(), cause);
		return c != null ? c.getEmployees() : null;
	}
	
	public boolean wasCapturedOperateTimeout() {
		return capturedOperateTimeout < TimeUpdater.getInstance().now();
	}
	
	public Player owner() {
		return getState() == State.CAPTURED && getAttackerId() != 0L ? attacker() : getManager().getOwner();
	}
	
	public Player attacker() {
		if (attackerId == 0L) {
			return null;
		}
//		return App.getApp().getServiceManager().get(ActorService.class).find(attackerId);
		Player p = App.getApp().getServiceManager().get(PlayerCacheService.class).find(attackerId);
		if (p == null) {
			attackerId = 0L;
		}
		return p;
	}
	
	public long[] employees() {
		Player attacker;
		Conquest c;
		if (getState() == State.CAPTURED
				&& getAttackerId() != 0L
				&& (attacker = attacker()) != null
				&& (c = attacker.getConquests().find(getManager().getOwner().getId(), getId())) != null) {
			return c.getEmployees();
		}
		return getEmployees();
	}
	
//	public int sizeOfEmployees() {
//		long[] eids = state == State.REST || state == State.CAPTURED ? employeesOfAttacker : employees;
//		int c = 0;
//		for (int i = 0, size = eids != null ? eids.length : 0; i < size; i++) {
//			if (eids[i] != 0L) {
//				c++;
//			}
//		}
//		return c;
//	}
	private BuildRef ref;
	public BuildRef refer() {
		if (ref == null) {
			BuildLevelUpTemplate next = getNextLevelTemplate();
			ItemInfo[] stuffs = next.getNeedItems();
			if (stuffs != null && stuffs.length > 0) {
				ref = new BuildRef(this, stuffs);
				for (ItemInfo stuff : stuffs) {
					getManager().addBagListener(stuff.getId(), this);
				}
			}
		}
		return ref;
	}

	@Override
	public void itemAdded(ItemTemplate item, int count) {
		BuildRef ref = refer();
		if (ref != null) {
			ref.itemAdded(item, count);
		}
	}

	@Override
	public void itemRemoved(ItemTemplate item, int count) {
		BuildRef ref = refer();
		if (ref != null) {
			ref.itemRemoved(item, count);
		}
	}
	
	
}
